/*
* ============================================================================
*  Name        : cameraengineprivate.h
*  Part of     : Symbian/S60 Camera Wrapper
*  Description : Camera engine (private) class declaration
*  Version     : %version: 2 %
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*
* You are welcome to, but not required to, contribute any modifications that
* improve stability, usability and/or feature set of the library back to
* Symbian/S60 Camera Wrapper project, as long as binary compatibility is
* retained. See https://projects.forum.nokia.com/camerawrapper for more info.
* ============================================================================
*/

/** @file cameraengineprivate.h */
 
#ifndef __CCAMERAENGINEPRIVATE_H__
#define __CCAMERAENGINEPRIVATE_H__

// INCLUDES
#include <ecam.h>                 // for MCameraObserver(2)
#include <ccamautofocus.h>        // for CCamAutoFocus, MCamAutoFocusObserver

#if defined(__S60_3X__) && !defined(__S60_50__)
#include <ecamadvancedsettings.h>
#else // S60 5.0, S^3
#include <ecamadvsettings.h>
#endif

// FORWARD DECLARATIONS
class MCameraEngineObserver;

/** @class CCameraEnginePrivate
  * @brief Camera engine (implementation) class.
  */
class CCameraEnginePrivate : public CBase,
                             public MCameraObserver,
                             public MCameraObserver2,              
                             public MCamAutoFocusObserver
  {
public:

  /**
   * @enum TCameraEngineState
   * @brief Enumeration for possible camera engine states.
   */
  enum TCameraEngineState
    {
    EEngineNotReady, 
    EEngineIdle,
    EEngineViewFinding,
    EEngineCapturing,
    EEngineFocusing
    };

  /**
   * Constructs a new camera engine instance.
   * @param aCameraHandle Handle (index) to a camera.
   * @see CamerasAvailable().
   * @param aPriority Value from -100 to 100 indicating relative 
   * priority of client to use camera. Ignored if the client does
   * not have MultimediaDD capability.
   * @param aObserver Pointer to class derived from MCameraEngineObserver
   * designed to receive notifications of asynchronous event completion.
   * @return CCameraEngine The new camera engine instance.
   * @leave May leave with one of the system-wide error codes.
   */
  static CCameraEnginePrivate* NewL( TInt aCameraHandle, 
                                     TInt aPriority, 
                                     MCameraEngineObserver* aObserver );
                                     
  /**
   * Destructor. Stops the viewfinder and releases all resources.
   */            
  ~CCameraEnginePrivate();
  
public:

  /**
   * Returns the current state of the camera engine.
   * @return TCameraEngineState state of the camera engine.
   */
  TCameraEngineState State() const
    {
    return iEngineState;
    }

  /**
   * Returns true if the camera has been reserved and
   * powered on.
   * @return TBool True if the camera is reserved and powered on.
   */
  TBool IsCameraReady() const 
    { 
    return iCameraReserved;
    }
  
  /**
   * Returns true if the camera supports AutoFocus.
   * @return TBool True if the camera supports AF.
   */
  TBool IsAutoFocusSupported() const;
  
  /**
   * Captures an image. When complete, observer will receive
   * MceoCapturedDataReady() or MceoCapturedBitmapReady() callback,
   * depending on which image format was used in PrepareL().
   * @leave May leave with KErrNotReady if camera is not
   * reserved or prepared for capture.
   */
  void CaptureL();
  
  /**
   * Reserves and powers on the camera. When complete,
   * observer will receive MceoCameraReady() callback.
   *
   */
  void ReserveAndPowerOn();
  
  /**
   * Releases and powers off the camera
   *
   */
  void ReleaseAndPowerOff();
  
  /**
   * Prepares the engine for image capture.
   * 
   * @param aCaptureSize Requested capture size.
   * - On return, contains the actual selected capture size.
   * @param aFormat Capture format to use.
   */
  void PrepareL( TSize& aCaptureSize,               
                 CCamera::TFormat aFormat = CCamera::EFormatExif );
  
  /**
   * Starts the viewfinder in bitmap mode. Observer will
   * receive viewfinder frames periodically in MceoViewFinderFrameReady.
   * @param aSize Requested viewfinder frame size - on return, contains 
   * the actual size used.
   */
  void StartViewFinderL( TSize& aSize );
  
  /**
   * Stops the viewfinder.
   * 
   */        
  void StopViewFinder();
                 
  /**
   * Releases last viewfinder buffer. Client must call this method after
   * drawing a viewfinder frame is complete in order to receive the next one.
   */     
  void ReleaseViewFinderBuffer();
  
  /**
   * Releases last captured image buffer. Client must call this method 
   * after it has completed handling the captured data.
   */     
  void ReleaseImageBuffer();
  
  /**
   * Starts the optimised autofocus operation. 
   * Does nothing if AutoFocus is not supported.
   */
  void StartFocusL();
        
  /**
   * Cancels an ongoing autofocus operation.
   */
  void FocusCancel();

  /**
   * Returns a bitfield of supported focus ranges.
   * @param aSupportedRanges On return, contains a bitfield of either
   * TAutoFocusRange (S60 3.0/3.1 devices) or TFocusRange 
   * (S60 3.2 and onwards) values.
   * @note Interpret the returned values as a bitfield of TFocusRange
   * values if AdvancedSettings() is not NULL, otherwise as 
   * TAutoFocusRange.
   */
  void SupportedFocusRanges( TInt& aSupportedRanges ) const;
  
  /**
   * Sets the focus range
   * @param aFocusRange one of the values returned by
   * SupportedFocusRanges().
   */
  void SetFocusRange( TInt aFocusRange );
  
  /**
   * Returns a pointer to CCamera object used by the engine.
   * Allows getting access to additional functionality
   * @brief From CCamera.
   * @note Do not use for functionality already provided
   * by other CCameraEngine methods!
   */
  CCamera* Camera() { return iCamera; }
  
  /**
   * Returns a pointer to CCameraAdvancedSettings object used by 
   * the engine. May be NULL if adv. settings is not available.
   * Allows getting access to additional functionality
   * @brief From CCameraAdvancedSettings.
   * @note Do not use for functionality already provided
   * by other CCameraEngine methods!
   */
  CCamera::CCameraAdvancedSettings* AdvancedSettings() { return iAdvSettings; }
  
  //static TInt CamerasAvailable() { return CCamera::CamerasAvailable(); }
  
  /**
   * Maximum digital zoom value. 0 if digital zoom is not supported.
   * @return TInt Maximum value supported by the digital zoom.
   */
  TInt MaxDigitalZoom() { return iCameraInfo.iMaxDigitalZoom; }
  
  /**
   * Returns the current digital zoom value.
   * @return TInt Current digital zoom value.
   */
  TInt DigitalZoom() { return iDigitalZoom; }
  
  /**
   * Adjusts digital zoom.
   * @param aTele Set to ETrue to increase zoom (tele) or EFalse to
   * decrease zoom (wide).
   * @return TInt Returns the new digital zoom level, or KErrNotSupported.
   */
  TInt AdjustDigitalZoom( TBool aTele );
  
  /**
   * Returns a bitfield of supported exposure modes.
   * @see CCamera::TExposure.
   * 
   */
  TInt SupportedExposureModes() { return iCameraInfo.iExposureModesSupported; }
  
  /**
   * Returns the current exposure mode.
   * @see CCamera::TExposure.
   */
  TInt Exposure() { return (TInt)iCamera->Exposure(); }
  
  /**
   * Set camera exposure mode.
   * @param aExposure One of the modes returned by SupportedExposureModes().
   * @return KErrNone or KErrNotSupported.
   * @see CCamera::TExposure.
   */
  TInt SetExposure( TInt aExposure );
  
  /**
   * Returns a bitfield of supported flash modes.
   * @see CCamera::TFlash.
   */  
  TInt SupportedFlashModes() { return iCameraInfo.iFlashModesSupported; }
  
  /**
   * Returns the current flash mode.
   * @see CCamera::TFlash.
   */
  TInt Flash() { return (TInt)iCamera->Flash(); }
  
  /**
   * Set camera flash mode.
   * @param aFlash One of the modes from SupportedFlashModes.
   * @return KErrNone or KErrNotSupported.
   * @see CCamera::TFlash.
   */
  TInt SetFlash( TInt aFlash );
   

protected:  // Protected constructors

  CCameraEnginePrivate( TInt aCameraHandle, 
                        TInt aPriority, 
                        MCameraEngineObserver* aObserver );
  void ConstructL();
  
protected: // Functions from inherited interfaces

        /**
         * @brief From MCameraObserver2.
         * Camera event handler
         */
        virtual void HandleEvent(const TECAMEvent &aEvent);
        
        /**
         * @brief From MCameraObserver2.
         * Notifies the client of new viewfinder data.
         */
        virtual void ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError);
        
        /**
         * @brief From MCameraObserver2.
         * Notifies the client of a new captured image.
         */
        virtual void ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError);
        
        /**
         * @brief From MCameraObserver2
         * Video capture not implemented.
         */
        virtual void VideoBufferReady(MCameraBuffer& /*aCameraBuffer*/, TInt /*aError*/) {}
        
        /**
         * @brief From MCameraObserver.
         * Gets called when CCamera::Reserve() is completed.
         * @note (V2: Called internally from HandleEvent).
         */
        virtual void ReserveComplete(TInt aError);

        /**
         * @brief From MCameraObserver.
         * Gets called when CCamera::PowerOn() is completed.
         * @note (V2: Called internally from HandleEvent).
         */
        virtual void PowerOnComplete(TInt aError);

        /**
         * @brief From MCameraObserver.
         * Gets called when CCamera::StartViewFinderBitmapsL() is completed.
         * @note (V2: Called internally from ViewFinderReady)
         */
        virtual void ViewFinderFrameReady( CFbsBitmap& aFrame );

        /**
         * @brief From MCameraObserver.
         * Gets called when CCamera::CaptureImage() is completed.
         */
        virtual void ImageReady( CFbsBitmap* aBitmap, HBufC8* aData, TInt aError );
        
        /**
         * @brief From MCameraObserver.
         * Video capture not implemented.
         */
        virtual void FrameBufferReady( MFrameBuffer* /*aFrameBuffer*/, 
                                       TInt /*aError*/ ) {}
        
        /**
        * @brief From MCamAutoFocusObserver.
        * Delivers notification of completion of auto focus initialisation to 
        * an interested party.
        * @param aError Reason for completion of focus request.
        */
        virtual void InitComplete( TInt aError );
        
        /**
         * @brief From MCamAutoFocusObserver.
         * Gets called when CCamAutoFocus::AttemptOptimisedFocusL() is
         * completed.
         * (V2: Called internally from HandleEvent)
         */
         virtual void OptimisedFocusComplete( TInt aError );
    
private:  // Internal functions

        /**
         * Internal function to handle ImageReady callbacks from
         * both observer (V1 & V2) interfaces
         */
         void HandleImageReady( CFbsBitmap* aBitmap, 
                                TDesC8* aData,  
                                TInt aError );
                                
private:  // Data

  CCamera*                          iCamera;
  TInt                              iCameraHandle;
  TInt                              iPriority;
  MCameraEngineObserver*            iObserver;
  TBool                             iCameraReserved;
  TCameraEngineState                iEngineState;
  TCameraInfo                       iCameraInfo;
  MCameraBuffer*                    iViewFinderBuffer;
  MCameraBuffer*                    iImageBuffer;
  HBufC8*                           iImageData;
  CFbsBitmap*                       iImageBitmap;
  
  CCamAutoFocus*                    iAutoFocus;
  CCamAutoFocus::TAutoFocusRange    iAFRange;  
  CCamera::CCameraAdvancedSettings* iAdvSettings;
  
  TInt                              iDigitalZoom;
  TSize                             iSelectedCaptureSize;
  CCamera::TFormat                  iSelectedCaptureFormat;
  };

#endif // __CCAMERAENGINEPRIVATE_H__
